/*******************************************************************************
 * Copyright (c) 2016-2017 Pivotal, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Pivotal, Inc. - initial API and implementation
 *******************************************************************************/

package org.springframework.ide.vscode.commons.javadoc.internal;

public class ScannerHelper {

	// storage for internal flags (32 bits)				BIT USAGE
	public final static int Bit1 = 0x1;					// return type (operator) | name reference kind (name ref) | add assertion (type decl) | useful empty statement (empty statement)
	public final static int Bit2 = 0x2;					// return type (operator) | name reference kind (name ref) | has local type (type, method, field decl) | if type elided (local)
	public final static int Bit3 = 0x4;					// return type (operator) | name reference kind (name ref) | implicit this (this ref) | is argument(local)
	public final static int Bit4 = 0x8;					// return type (operator) | first assignment to local (name ref,local decl) | undocumented empty block (block, type and method decl)
	public final static int Bit5 = 0x10;					// value for return (expression) | has all method bodies (unit) | supertype ref (type ref) | resolved (field decl)
	public final static int Bit6 = 0x20;					// depth (name ref, msg) | ignore need cast check (cast expression) | error in signature (method declaration/ initializer) | is recovered (annotation reference)
	public final static int Bit7 = 0x40;					// depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement) | needFreeReturn (AbstractMethodDeclaration)
	public final static int Bit8 = 0x80;					// depth (name ref, msg) | operator (operator) | unsafe cast (cast expression) | is default constructor (constructor declaration) | isElseStatementUnreachable (if statement)
	public final static int Bit9 = 0x100;				// depth (name ref, msg) | operator (operator) | is local type (type decl) | isThenStatementUnreachable (if statement) | can be static
	public final static int Bit10= 0x200;				// depth (name ref, msg) | operator (operator) | is anonymous type (type decl)
	public final static int Bit11 = 0x400;				// depth (name ref, msg) | operator (operator) | is member type (type decl)
	public final static int Bit12 = 0x800;				// depth (name ref, msg) | operator (operator) | has abstract methods (type decl)
	public final static int Bit13 = 0x1000;			// depth (name ref, msg) | is secondary type (type decl)
	public final static int Bit14 = 0x2000;			// strictly assigned (reference lhs) | discard enclosing instance (explicit constr call) | hasBeenGenerated (type decl)
	public final static int Bit15 = 0x4000;			// is unnecessary cast (expression) | is varargs (type ref) | isSubRoutineEscaping (try statement) | superAccess (javadoc allocation expression/javadoc message send/javadoc return statement)
	public final static int Bit16 = 0x8000;			// in javadoc comment (name ref, type ref, msg)
	public final static int Bit17 = 0x10000;			// compound assigned (reference lhs) | unchecked (msg, alloc, explicit constr call)
	public final static int Bit18 = 0x20000;			// non null (expression) | onDemand (import reference)
	public final static int Bit19 = 0x40000;			// didResolve (parameterized qualified type ref/parameterized single type ref)  | empty (javadoc return statement) | needReceiverGenericCast (msg/fieldref)
	public final static int Bit20 = 0x80000;			// contains syntax errors (method declaration, type declaration, field declarations, initializer), typeref: <> name ref: lambda capture)
	public final static int Bit21 = 0x100000;
	public final static int Bit22 = 0x200000;			// parenthesis count (expression) | used (import reference) shadows outer local (local declarations)
	public final static int Bit23 = 0x400000;			// parenthesis count (expression)
	public final static int Bit24 = 0x800000;			// parenthesis count (expression)
	public final static int Bit25 = 0x1000000;		// parenthesis count (expression)
	public final static int Bit26 = 0x2000000;		// parenthesis count (expression)
	public final static int Bit27 = 0x4000000;		// parenthesis count (expression)
	public final static int Bit28 = 0x8000000;		// parenthesis count (expression)
	public final static int Bit29 = 0x10000000;		// parenthesis count (expression)
	public final static int Bit30 = 0x20000000;		// elseif (if statement) | try block exit (try statement) | fall-through (case statement) | ignore no effect assign (expression ref) | needScope (for statement) | isAnySubRoutineEscaping (return statement) | blockExit (synchronized statement)
	public final static int Bit31 = 0x40000000;		// local declaration reachable (local decl) | ignore raw type check (type ref) | discard entire assignment (assignment) | isSynchronized (return statement) | thenExit (if statement)
	public final static int Bit32 = 0x80000000;		// reachable (statement)
	
//	public final static long[] Bits = {
//		ASTNode.Bit1, ASTNode.Bit2, ASTNode.Bit3, ASTNode.Bit4, ASTNode.Bit5, ASTNode.Bit6,
//		ASTNode.Bit7, ASTNode.Bit8, ASTNode.Bit9, ASTNode.Bit10, ASTNode.Bit11, ASTNode.Bit12,
//		ASTNode.Bit13, ASTNode.Bit14, ASTNode.Bit15, ASTNode.Bit16, ASTNode.Bit17, ASTNode.Bit18,
//		ASTNode.Bit19, ASTNode.Bit20, ASTNode.Bit21, ASTNode.Bit22, ASTNode.Bit23, ASTNode.Bit24,
//		ASTNode.Bit25, ASTNode.Bit26, ASTNode.Bit27, ASTNode.Bit28, ASTNode.Bit29, ASTNode.Bit30,
//		ASTNode.Bit31, ASTNode.Bit32L, ASTNode.Bit33L, ASTNode.Bit34L, ASTNode.Bit35L, ASTNode.Bit36L,
//		ASTNode.Bit37L, ASTNode.Bit38L, ASTNode.Bit39L, ASTNode.Bit40L, ASTNode.Bit41L, ASTNode.Bit42L,
//		ASTNode.Bit43L, ASTNode.Bit44L, ASTNode.Bit45L, ASTNode.Bit46L, ASTNode.Bit47L, ASTNode.Bit48L,
//		ASTNode.Bit49L, ASTNode.Bit50L, ASTNode.Bit51L, ASTNode.Bit52L, ASTNode.Bit53L, ASTNode.Bit54L,
//		ASTNode.Bit55L, ASTNode.Bit56L, ASTNode.Bit57L, ASTNode.Bit58L, ASTNode.Bit59L, ASTNode.Bit60L,
//		ASTNode.Bit61L, ASTNode.Bit62L, ASTNode.Bit63L, ASTNode.Bit64L,
//	};
//
//	private static final int START_INDEX = 0;
//	private static final int PART_INDEX = 1;
//
//	private static long[][][] Tables;
//	private static long[][][] Tables7;
//	private static long[][][] Tables8;

	public final static int MAX_OBVIOUS = 128;
	public final static int[] OBVIOUS_IDENT_CHAR_NATURES = new int[MAX_OBVIOUS];

	public final static int C_JLS_SPACE = Bit9;
	public final static int C_SPECIAL = Bit8;
	public final static int C_IDENT_START = Bit7;
	public final static int C_UPPER_LETTER = Bit6;
	public final static int C_LOWER_LETTER = Bit5;
	public final static int C_IDENT_PART = Bit4;
	public final static int C_DIGIT = Bit3;
	public final static int C_SEPARATOR = Bit2;
	public final static int C_SPACE = Bit1;

	static {
		OBVIOUS_IDENT_CHAR_NATURES[0] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[1] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[2] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[3] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[4] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[5] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[6] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[7] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[8] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[14] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[15] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[16] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[17] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[18] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[19] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[20] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[21] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[22] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[23] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[24] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[25] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[26] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[27] = C_IDENT_PART;
		OBVIOUS_IDENT_CHAR_NATURES[127] = C_IDENT_PART;

		for (int i = '0'; i <= '9'; i++)
			OBVIOUS_IDENT_CHAR_NATURES[i] = C_DIGIT | C_IDENT_PART;

		for (int i = 'a'; i <= 'z'; i++)
			OBVIOUS_IDENT_CHAR_NATURES[i] = C_LOWER_LETTER | C_IDENT_PART | C_IDENT_START;
		for (int i = 'A'; i <= 'Z'; i++)
			OBVIOUS_IDENT_CHAR_NATURES[i] = C_UPPER_LETTER | C_IDENT_PART | C_IDENT_START;

		OBVIOUS_IDENT_CHAR_NATURES['_'] = C_SPECIAL | C_IDENT_PART | C_IDENT_START;
		OBVIOUS_IDENT_CHAR_NATURES['$'] = C_SPECIAL | C_IDENT_PART | C_IDENT_START;

		OBVIOUS_IDENT_CHAR_NATURES[9] = C_SPACE | C_JLS_SPACE; // \ u0009: HORIZONTAL TABULATION
		OBVIOUS_IDENT_CHAR_NATURES[10] = C_SPACE | C_JLS_SPACE; // \ u000a: LINE FEED
		OBVIOUS_IDENT_CHAR_NATURES[11] = C_SPACE;
		OBVIOUS_IDENT_CHAR_NATURES[12] = C_SPACE | C_JLS_SPACE; // \ u000c: FORM FEED
		OBVIOUS_IDENT_CHAR_NATURES[13] = C_SPACE | C_JLS_SPACE; //  \ u000d: CARRIAGE RETURN
		OBVIOUS_IDENT_CHAR_NATURES[28] = C_SPACE;
		OBVIOUS_IDENT_CHAR_NATURES[29] = C_SPACE;
		OBVIOUS_IDENT_CHAR_NATURES[30] = C_SPACE;
		OBVIOUS_IDENT_CHAR_NATURES[31] = C_SPACE;
		OBVIOUS_IDENT_CHAR_NATURES[32] = C_SPACE | C_JLS_SPACE; //  \ u0020: SPACE

		OBVIOUS_IDENT_CHAR_NATURES['.'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES[':'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES[';'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES[','] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['['] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES[']'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['('] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES[')'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['{'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['}'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['+'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['-'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['*'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['/'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['='] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['&'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['|'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['?'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['<'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['>'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['!'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['%'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['^'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['~'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['"'] = C_SEPARATOR;
		OBVIOUS_IDENT_CHAR_NATURES['\''] = C_SEPARATOR;
	}
//static void initializeTable() {
//	Tables = initializeTables("unicode"); //$NON-NLS-1$
//}
//static void initializeTable17() {
//	Tables7 = initializeTables("unicode6"); //$NON-NLS-1$
//}
//static void initializeTable18() {
//	Tables8 = initializeTables("unicode6_2"); //$NON-NLS-1$
//}
//static long[][][] initializeTables(String unicode_path) {
//	long[][][] tempTable = new long[2][][];
//	tempTable[START_INDEX] = new long[3][];
//	tempTable[PART_INDEX] = new long[4][];
//	try {
//		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/start0.rsc"))); //$NON-NLS-1$
//		long[] readValues = new long[1024];
//		for (int i = 0; i < 1024; i++) {
//			readValues[i] = inputStream.readLong();
//		}
//		inputStream.close();
//		tempTable[START_INDEX][0] = readValues;
//	} catch (FileNotFoundException e) {
//		e.printStackTrace();
//	} catch (IOException e) {
//		e.printStackTrace();
//	}
//	try {
//		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/start1.rsc"))); //$NON-NLS-1$
//		long[] readValues = new long[1024];
//		for (int i = 0; i < 1024; i++) {
//			readValues[i] = inputStream.readLong();
//		}
//		inputStream.close();
//		tempTable[START_INDEX][1] = readValues;
//	} catch (FileNotFoundException e) {
//		e.printStackTrace();
//	} catch (IOException e) {
//		e.printStackTrace();
//	}
//	try {
//		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/start2.rsc"))); //$NON-NLS-1$
//		long[] readValues = new long[1024];
//		for (int i = 0; i < 1024; i++) {
//			readValues[i] = inputStream.readLong();
//		}
//		inputStream.close();
//		tempTable[START_INDEX][2] = readValues;
//	} catch (FileNotFoundException e) {
//		e.printStackTrace();
//	} catch (IOException e) {
//		e.printStackTrace();
//	}
//	try {
//		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/part0.rsc"))); //$NON-NLS-1$
//		long[] readValues = new long[1024];
//		for (int i = 0; i < 1024; i++) {
//			readValues[i] = inputStream.readLong();
//		}
//		inputStream.close();
//		tempTable[PART_INDEX][0] = readValues;
//	} catch (FileNotFoundException e) {
//		e.printStackTrace();
//	} catch (IOException e) {
//		e.printStackTrace();
//	}
//	try {
//		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/part1.rsc"))); //$NON-NLS-1$
//		long[] readValues = new long[1024];
//		for (int i = 0; i < 1024; i++) {
//			readValues[i] = inputStream.readLong();
//		}
//		inputStream.close();
//		tempTable[PART_INDEX][1] = readValues;
//	} catch (FileNotFoundException e) {
//		e.printStackTrace();
//	} catch (IOException e) {
//		e.printStackTrace();
//	}
//	try {
//		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/part2.rsc"))); //$NON-NLS-1$
//		long[] readValues = new long[1024];
//		for (int i = 0; i < 1024; i++) {
//			readValues[i] = inputStream.readLong();
//		}
//		inputStream.close();
//		tempTable[PART_INDEX][2] = readValues;
//	} catch (FileNotFoundException e) {
//		e.printStackTrace();
//	} catch (IOException e) {
//		e.printStackTrace();
//	}
//	try {
//		DataInputStream inputStream = new DataInputStream(new BufferedInputStream(ScannerHelper.class.getResourceAsStream(unicode_path + "/part14.rsc"))); //$NON-NLS-1$
//		long[] readValues = new long[1024];
//		for (int i = 0; i < 1024; i++) {
//			readValues[i] = inputStream.readLong();
//		}
//		inputStream.close();
//		tempTable[PART_INDEX][3] = readValues;
//	} catch (FileNotFoundException e) {
//		e.printStackTrace();
//	} catch (IOException e) {
//		e.printStackTrace();
//	}
//	return tempTable;
//}
//private final static boolean isBitSet(long[] values, int i) {
//	try {
//		return (values[i / 64] & Bits[i % 64]) != 0;
//	} catch (NullPointerException e) {
//		return false;
//	}
//}
//public static boolean isJavaIdentifierPart(char c) {
//	if (c < MAX_OBVIOUS) {
//		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_PART) != 0;
//	}
//	return Character.isJavaIdentifierPart(c);
//}
///**
// * @param complianceLevel
// * @param c
// * @return
// */
//public static boolean isJavaIdentifierPart(long complianceLevel, char c) {
//	if (c < MAX_OBVIOUS) {
//		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_PART) != 0;
//	}
//	return isJavaIdentifierPart(complianceLevel, (int) c);
//}
///**
// * @param complianceLevel
// * @param codePoint
// * @return
// */
//public static boolean isJavaIdentifierPart(long complianceLevel, int codePoint) {
//	if (complianceLevel <= ClassFileConstants.JDK1_6) {
//		if (Tables == null) {
//			initializeTable();
//		}
//		switch((codePoint & 0x1F0000) >> 16) {
//			case 0 :
//				return isBitSet(Tables[PART_INDEX][0], codePoint & 0xFFFF);
//			case 1 :
//				return isBitSet(Tables[PART_INDEX][1], codePoint & 0xFFFF);
//			case 2 :
//				return isBitSet(Tables[PART_INDEX][2], codePoint & 0xFFFF);
//			case 14 :
//				return isBitSet(Tables[PART_INDEX][3], codePoint & 0xFFFF);
//		}
//	} else if (complianceLevel <= ClassFileConstants.JDK1_7) {
//		// java 7 supports Unicode 6
//		if (Tables7 == null) {
//			initializeTable17();
//		}
//		switch((codePoint & 0x1F0000) >> 16) {
//			case 0 :
//				return isBitSet(Tables7[PART_INDEX][0], codePoint & 0xFFFF);
//			case 1 :
//				return isBitSet(Tables7[PART_INDEX][1], codePoint & 0xFFFF);
//			case 2 :
//				return isBitSet(Tables7[PART_INDEX][2], codePoint & 0xFFFF);
//			case 14 :
//				return isBitSet(Tables7[PART_INDEX][3], codePoint & 0xFFFF);
//		}
//	} else {
//		// java 7 supports Unicode 6.2
//		if (Tables8 == null) {
//			initializeTable18();
//		}
//		switch((codePoint & 0x1F0000) >> 16) {
//			case 0 :
//				return isBitSet(Tables8[PART_INDEX][0], codePoint & 0xFFFF);
//			case 1 :
//				return isBitSet(Tables8[PART_INDEX][1], codePoint & 0xFFFF);
//			case 2 :
//				return isBitSet(Tables8[PART_INDEX][2], codePoint & 0xFFFF);
//			case 14 :
//				return isBitSet(Tables8[PART_INDEX][3], codePoint & 0xFFFF);
//		}
//	}
//	return false;
//}
///**
// * @param complianceLevel
// * @param high
// * @param low
// * @return
// */
//public static boolean isJavaIdentifierPart(long complianceLevel, char high, char low) {
//	return isJavaIdentifierPart(complianceLevel, toCodePoint(high, low));
//}
///**
// * @param c
// * @return
// */
//public static boolean isJavaIdentifierStart(char c) {
//	if (c < MAX_OBVIOUS) {
//		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0;
//	}
//	return Character.isJavaIdentifierStart(c);
//}
///**
// * @param complianceLevel
// * @param c
// * @return
// */
//public static boolean isJavaIdentifierStart(long complianceLevel, char c) {
//	if (c < MAX_OBVIOUS) {
//		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_IDENT_START) != 0;
//	}
//	return ScannerHelper.isJavaIdentifierStart(complianceLevel, (int) c);
//}
///**
// * @param complianceLevel
// * @param high
// * @param low
// * @return
// */
//public static boolean isJavaIdentifierStart(long complianceLevel, char high, char low) {
//	return isJavaIdentifierStart(complianceLevel, toCodePoint(high, low));
//}
///**
// * @param complianceLevel
// * @param codePoint
// * @return
// */
//public static boolean isJavaIdentifierStart(long complianceLevel, int codePoint) {
//	if (complianceLevel <= ClassFileConstants.JDK1_6) {
//		if (Tables == null) {
//			initializeTable();
//		}
//		switch((codePoint & 0x1F0000) >> 16) {
//			case 0 :
//				return isBitSet(Tables[START_INDEX][0], codePoint & 0xFFFF);
//			case 1 :
//				return isBitSet(Tables[START_INDEX][1], codePoint & 0xFFFF);
//			case 2 :
//				return isBitSet(Tables[START_INDEX][2], codePoint & 0xFFFF);
//		}
//	} else if (complianceLevel <= ClassFileConstants.JDK1_7) {
//		// java 7 supports Unicode 6
//		if (Tables7 == null) {
//			initializeTable17();
//		}
//		switch((codePoint & 0x1F0000) >> 16) {
//			case 0 :
//				return isBitSet(Tables7[START_INDEX][0], codePoint & 0xFFFF);
//			case 1 :
//				return isBitSet(Tables7[START_INDEX][1], codePoint & 0xFFFF);
//			case 2 :
//				return isBitSet(Tables7[START_INDEX][2], codePoint & 0xFFFF);
//		}
//	} else {
//		// java 7 supports Unicode 6
//		if (Tables8 == null) {
//			initializeTable18();
//		}
//		switch((codePoint & 0x1F0000) >> 16) {
//			case 0 :
//				return isBitSet(Tables8[START_INDEX][0], codePoint & 0xFFFF);
//			case 1 :
//				return isBitSet(Tables8[START_INDEX][1], codePoint & 0xFFFF);
//			case 2 :
//				return isBitSet(Tables8[START_INDEX][2], codePoint & 0xFFFF);
//		}
//	}
//	return false;
//}
//private static int toCodePoint(char high, char low) {
//	return (high - Scanner.HIGH_SURROGATE_MIN_VALUE) * 0x400 + (low - Scanner.LOW_SURROGATE_MIN_VALUE) + 0x10000;
//}
//public static boolean isDigit(char c) throws InvalidInputException {
//	if(c < ScannerHelper.MAX_OBVIOUS) {
//		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_DIGIT) != 0;
//	}
//	if (Character.isDigit(c)) {
//		throw new InvalidStateException(Scanner.INVALID_DIGIT);
//	}
//	return false;
//}
public static int digit(char c, int radix) {
	if (c < ScannerHelper.MAX_OBVIOUS) {
		switch(radix) {
			case 8 :
				if (c >= 48 && c <= 55) {
					return c - 48;
				}
				return -1;
			case 10 :
				if (c >= 48 && c <= 57) {
					return c - 48;
				}
				return -1;
			case 16 :
				if (c >= 48 && c <= 57) {
					return c - 48;
				}
				if (c >= 65 && c <= 70) {
					return c - 65 + 10;
				}
				if (c >= 97 && c <= 102) {
					return c - 97 + 10;
				}
				return -1;
		}
	}
	return Character.digit(c, radix);
}
public static int getNumericValue(char c) {
	if (c < ScannerHelper.MAX_OBVIOUS) {
		switch(ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c]) {
			case C_DIGIT :
				return c - '0';
			case C_LOWER_LETTER :
				return 10 + c - 'a';
			case C_UPPER_LETTER :
				return 10 + c - 'A';
		}
	}
	return Character.getNumericValue(c);
}
public static int getHexadecimalValue(char c) {
	switch(c) {
		case '0' :
			return 0;
		case '1' :
			return 1;
		case '2' :
			return 2;
		case '3' :
			return 3;
		case '4' :
			return 4;
		case '5' :
			return 5;
		case '6' :
			return 6;
		case '7' :
			return 7;
		case '8' :
			return 8;
		case '9' :
			return 9;
		case 'A' :
		case 'a' :
			return 10;
		case 'B' :
		case 'b' :
			return 11;
		case 'C' :
		case 'c' :
			return 12;
		case 'D' :
		case 'd' :
			return 13;
		case 'E' :
		case 'e' :
			return 14;
		case 'F' :
		case 'f' :
			return 15;
		default:
			return -1;
	}
}
public static char toUpperCase(char c) {
	if (c < MAX_OBVIOUS) {
		if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0) {
			return c;
		} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_LOWER_LETTER) != 0) {
			return (char) (c - 32);
		}
	}
	return Character.toUpperCase(c);
}
public static char toLowerCase(char c) {
	if (c < MAX_OBVIOUS) {
		if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_LOWER_LETTER) != 0) {
			return c;
		} else if ((ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0) {
			return (char) (32 + c);
		}
	}
	return Character.toLowerCase(c);
}
public static boolean isLowerCase(char c) {
	if (c < MAX_OBVIOUS) {
		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_LOWER_LETTER) != 0;
	}
	return Character.isLowerCase(c);
}
public static boolean isUpperCase(char c) {
	if (c < MAX_OBVIOUS) {
		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_UPPER_LETTER) != 0;
	}
	return Character.isUpperCase(c);
}
/**
 * Include also non JLS whitespaces.
 *
 * return true if Character.isWhitespace(c) would return true
 */
public static boolean isWhitespace(char c) {
	if (c < MAX_OBVIOUS) {
		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & ScannerHelper.C_SPACE) != 0;
	}
	return Character.isWhitespace(c);
}
public static boolean isLetter(char c) {
	if (c < MAX_OBVIOUS) {
		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER)) != 0;
	}
	return Character.isLetter(c);
}
public static boolean isLetterOrDigit(char c) {
	if (c < MAX_OBVIOUS) {
		return (ScannerHelper.OBVIOUS_IDENT_CHAR_NATURES[c] & (ScannerHelper.C_UPPER_LETTER | ScannerHelper.C_LOWER_LETTER | ScannerHelper.C_DIGIT)) != 0;
	}
	return Character.isLetterOrDigit(c);
}
}
